#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
SQL编辑器性能监控模块
监控编辑器性能并提供优化建议
"""

import time
import logging
import threading
from typing import Dict, List, Optional, Callable
from dataclasses import dataclass, field
from collections import deque
import psutil
import gc

from PySide6.QtCore import QObject, Signal, QTimer, QThread
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel, QProgressBar

logger = logging.getLogger("performance_monitor")


@dataclass
class PerformanceMetric:
    """性能指标"""
    name: str
    value: float
    unit: str
    timestamp: float = field(default_factory=time.time)
    threshold_warning: float = 0.0
    threshold_critical: float = 0.0


@dataclass
class PerformanceReport:
    """性能报告"""
    timestamp: float
    cpu_usage: float
    memory_usage: float
    response_time: float
    document_size: int
    line_count: int
    suggestions: List[str] = field(default_factory=list)


class PerformanceCollector(QThread):
    """性能数据收集器"""
    
    metrics_updated = Signal(dict)  # 性能指标更新信号
    
    def __init__(self, parent=None):
        """初始化性能收集器"""
        super().__init__(parent)
        self.running = False
        self.collection_interval = 1.0  # 1秒收集一次
        self.metrics_history = deque(maxlen=100)  # 保留最近100个数据点
        
    def start_monitoring(self):
        """开始监控"""
        self.running = True
        self.start()
        
    def stop_monitoring(self):
        """停止监控"""
        self.running = False
        self.quit()
        self.wait()
        
    def run(self):
        """运行监控循环"""
        while self.running:
            try:
                metrics = self._collect_metrics()
                self.metrics_history.append(metrics)
                self.metrics_updated.emit(metrics)
                
                time.sleep(self.collection_interval)
                
            except Exception as e:
                logger.error(f"性能监控出错: {str(e)}")
                time.sleep(self.collection_interval)
                
    def _collect_metrics(self) -> Dict[str, PerformanceMetric]:
        """收集性能指标"""
        metrics = {}
        
        # CPU使用率
        cpu_percent = psutil.cpu_percent(interval=0.1)
        metrics['cpu_usage'] = PerformanceMetric(
            name="CPU使用率",
            value=cpu_percent,
            unit="%",
            threshold_warning=70.0,
            threshold_critical=90.0
        )
        
        # 内存使用率
        memory = psutil.virtual_memory()
        metrics['memory_usage'] = PerformanceMetric(
            name="内存使用率",
            value=memory.percent,
            unit="%",
            threshold_warning=80.0,
            threshold_critical=95.0
        )
        
        # 进程内存使用
        process = psutil.Process()
        process_memory = process.memory_info().rss / 1024 / 1024  # MB
        metrics['process_memory'] = PerformanceMetric(
            name="进程内存",
            value=process_memory,
            unit="MB",
            threshold_warning=500.0,
            threshold_critical=1000.0
        )
        
        return metrics


class EditorPerformanceMonitor(QObject):
    """编辑器性能监控器"""
    
    performance_warning = Signal(str)  # 性能警告信号
    optimization_suggested = Signal(str)  # 优化建议信号
    
    def __init__(self, editor):
        """初始化编辑器性能监控器
        
        Args:
            editor: SQL编辑器实例
        """
        super().__init__()
        self.editor = editor
        self.collector = PerformanceCollector()
        
        # 性能阈值
        self.response_time_threshold = 0.1  # 100ms
        self.document_size_threshold = 1024 * 1024  # 1MB
        self.line_count_threshold = 10000  # 10000行
        
        # 操作计时
        self.operation_times = deque(maxlen=50)
        self.last_operation_start = None
        
        # 连接信号
        self.collector.metrics_updated.connect(self._on_metrics_updated)
        
        # 连接编辑器信号
        if hasattr(self.editor, 'textChanged'):
            self.editor.textChanged.connect(self._on_text_changed)
        if hasattr(self.editor, 'cursorPositionChanged'):
            self.editor.cursorPositionChanged.connect(self._on_cursor_changed)
            
        # 启动监控
        self.collector.start_monitoring()
        
    def _on_metrics_updated(self, metrics: Dict[str, PerformanceMetric]):
        """处理性能指标更新"""
        # 检查是否超过阈值
        for metric in metrics.values():
            if metric.value > metric.threshold_critical:
                self.performance_warning.emit(
                    f"严重警告: {metric.name} 达到 {metric.value:.1f}{metric.unit}"
                )
            elif metric.value > metric.threshold_warning:
                self.performance_warning.emit(
                    f"警告: {metric.name} 达到 {metric.value:.1f}{metric.unit}"
                )
                
        # 生成优化建议
        self._generate_optimization_suggestions(metrics)
        
    def _generate_optimization_suggestions(self, metrics: Dict[str, PerformanceMetric]):
        """生成优化建议"""
        suggestions = []
        
        # CPU使用率过高
        if metrics.get('cpu_usage', PerformanceMetric('', 0, '')).value > 70:
            suggestions.append("CPU使用率较高，建议减少语法高亮的复杂度或增加更新延迟")
            
        # 内存使用率过高
        if metrics.get('memory_usage', PerformanceMetric('', 0, '')).value > 80:
            suggestions.append("内存使用率较高，建议清理未使用的资源或减少缓存大小")
            
        # 文档过大
        if hasattr(self.editor, 'document') and self.editor.document():
            doc_size = len(self.editor.toPlainText().encode('utf-8'))
            if doc_size > self.document_size_threshold:
                suggestions.append(f"文档大小 ({doc_size/1024/1024:.1f}MB) 较大，建议分割为多个文件")
                
        # 行数过多
        if hasattr(self.editor, 'document') and self.editor.document():
            line_count = self.editor.document().blockCount()
            if line_count > self.line_count_threshold:
                suggestions.append(f"文档行数 ({line_count}) 过多，可能影响性能")
                
        # 响应时间过长
        if self.operation_times:
            avg_response_time = sum(self.operation_times) / len(self.operation_times)
            if avg_response_time > self.response_time_threshold:
                suggestions.append(f"平均响应时间 ({avg_response_time*1000:.1f}ms) 过长，建议优化操作")
                
        # 发送建议
        for suggestion in suggestions:
            self.optimization_suggested.emit(suggestion)
            
    def _on_text_changed(self):
        """文本改变时的性能监控"""
        self._start_operation_timing()
        
        # 检查文档大小
        if hasattr(self.editor, 'toPlainText'):
            text = self.editor.toPlainText()
            doc_size = len(text.encode('utf-8'))
            
            if doc_size > self.document_size_threshold:
                self.performance_warning.emit(
                    f"文档大小 ({doc_size/1024/1024:.1f}MB) 可能影响性能"
                )
                
    def _on_cursor_changed(self):
        """光标位置改变时的性能监控"""
        self._end_operation_timing()
        
    def _start_operation_timing(self):
        """开始操作计时"""
        self.last_operation_start = time.time()
        
    def _end_operation_timing(self):
        """结束操作计时"""
        if self.last_operation_start:
            operation_time = time.time() - self.last_operation_start
            self.operation_times.append(operation_time)
            self.last_operation_start = None
            
            # 检查响应时间
            if operation_time > self.response_time_threshold:
                self.performance_warning.emit(
                    f"操作响应时间 ({operation_time*1000:.1f}ms) 过长"
                )
                
    def get_performance_report(self) -> PerformanceReport:
        """获取性能报告"""
        report = PerformanceReport(
            timestamp=time.time(),
            cpu_usage=0.0,
            memory_usage=0.0,
            response_time=0.0,
            document_size=0,
            line_count=0
        )
        
        # 获取最新的性能指标
        if self.collector.metrics_history:
            latest_metrics = self.collector.metrics_history[-1]
            report.cpu_usage = latest_metrics.get('cpu_usage', PerformanceMetric('', 0, '')).value
            report.memory_usage = latest_metrics.get('memory_usage', PerformanceMetric('', 0, '')).value
            
        # 获取编辑器信息
        if hasattr(self.editor, 'toPlainText'):
            text = self.editor.toPlainText()
            report.document_size = len(text.encode('utf-8'))
            
        if hasattr(self.editor, 'document') and self.editor.document():
            report.line_count = self.editor.document().blockCount()
            
        # 计算平均响应时间
        if self.operation_times:
            report.response_time = sum(self.operation_times) / len(self.operation_times)
            
        return report
        
    def cleanup(self):
        """清理资源"""
        self.collector.stop_monitoring()


class PerformanceOptimizer:
    """性能优化器"""
    
    def __init__(self, editor):
        """初始化性能优化器
        
        Args:
            editor: SQL编辑器实例
        """
        self.editor = editor
        self.optimizations_applied = set()
        
    def apply_optimizations(self, report: PerformanceReport):
        """应用性能优化
        
        Args:
            report: 性能报告
        """
        # 文档过大时的优化
        if report.document_size > 1024 * 1024:  # 1MB
            self._optimize_large_document()
            
        # 行数过多时的优化
        if report.line_count > 10000:
            self._optimize_many_lines()
            
        # 响应时间过长时的优化
        if report.response_time > 0.1:  # 100ms
            self._optimize_response_time()
            
        # CPU使用率过高时的优化
        if report.cpu_usage > 70:
            self._optimize_cpu_usage()
            
        # 内存使用率过高时的优化
        if report.memory_usage > 80:
            self._optimize_memory_usage()
            
    def _optimize_large_document(self):
        """优化大文档"""
        if 'large_document' not in self.optimizations_applied:
            # 禁用一些耗性能的功能
            if hasattr(self.editor, 'highlighter'):
                # 减少语法高亮的复杂度
                pass
                
            # 增加更新延迟
            if hasattr(self.editor, '_update_delay'):
                self.editor._update_delay = 200  # 增加到200ms
                
            self.optimizations_applied.add('large_document')
            logger.info("应用大文档优化")
            
    def _optimize_many_lines(self):
        """优化多行文档"""
        if 'many_lines' not in self.optimizations_applied:
            # 启用虚拟化滚动（如果支持）
            if hasattr(self.editor, 'setMaximumBlockCount'):
                self.editor.setMaximumBlockCount(5000)  # 限制显示的块数
                
            self.optimizations_applied.add('many_lines')
            logger.info("应用多行优化")
            
    def _optimize_response_time(self):
        """优化响应时间"""
        if 'response_time' not in self.optimizations_applied:
            # 增加操作延迟
            if hasattr(self.editor, '_update_delay'):
                self.editor._update_delay = max(self.editor._update_delay, 100)
                
            self.optimizations_applied.add('response_time')
            logger.info("应用响应时间优化")
            
    def _optimize_cpu_usage(self):
        """优化CPU使用率"""
        if 'cpu_usage' not in self.optimizations_applied:
            # 减少语法高亮频率
            if hasattr(self.editor, 'highlighter'):
                # 可以考虑暂时禁用语法高亮
                pass
                
            self.optimizations_applied.add('cpu_usage')
            logger.info("应用CPU优化")
            
    def _optimize_memory_usage(self):
        """优化内存使用"""
        if 'memory_usage' not in self.optimizations_applied:
            # 强制垃圾回收
            gc.collect()
            
            # 清理缓存
            if hasattr(self.editor, 'completer') and self.editor.completer:
                # 清理补全缓存
                pass
                
            self.optimizations_applied.add('memory_usage')
            logger.info("应用内存优化")


class PerformanceWidget(QWidget):
    """性能监控显示组件"""
    
    def __init__(self, monitor: EditorPerformanceMonitor, parent=None):
        """初始化性能监控显示组件
        
        Args:
            monitor: 性能监控器
            parent: 父窗口
        """
        super().__init__(parent)
        self.monitor = monitor
        self._init_ui()
        
        # 连接信号
        self.monitor.collector.metrics_updated.connect(self._update_display)
        
        # 更新定时器
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self._update_report)
        self.update_timer.start(5000)  # 每5秒更新一次报告
        
    def _init_ui(self):
        """初始化用户界面"""
        layout = QVBoxLayout(self)
        
        # CPU使用率
        self.cpu_label = QLabel("CPU: 0%")
        layout.addWidget(self.cpu_label)
        
        self.cpu_bar = QProgressBar()
        self.cpu_bar.setRange(0, 100)
        layout.addWidget(self.cpu_bar)
        
        # 内存使用率
        self.memory_label = QLabel("内存: 0%")
        layout.addWidget(self.memory_label)
        
        self.memory_bar = QProgressBar()
        self.memory_bar.setRange(0, 100)
        layout.addWidget(self.memory_bar)
        
        # 响应时间
        self.response_label = QLabel("响应时间: 0ms")
        layout.addWidget(self.response_label)
        
        # 文档信息
        self.doc_info_label = QLabel("文档: 0 行, 0 KB")
        layout.addWidget(self.doc_info_label)
        
    def _update_display(self, metrics: Dict[str, PerformanceMetric]):
        """更新显示"""
        # 更新CPU
        cpu_metric = metrics.get('cpu_usage')
        if cpu_metric:
            self.cpu_label.setText(f"CPU: {cpu_metric.value:.1f}%")
            self.cpu_bar.setValue(int(cpu_metric.value))
            
        # 更新内存
        memory_metric = metrics.get('memory_usage')
        if memory_metric:
            self.memory_label.setText(f"内存: {memory_metric.value:.1f}%")
            self.memory_bar.setValue(int(memory_metric.value))
            
    def _update_report(self):
        """更新报告信息"""
        report = self.monitor.get_performance_report()
        
        # 更新响应时间
        self.response_label.setText(f"响应时间: {report.response_time*1000:.1f}ms")
        
        # 更新文档信息
        doc_size_kb = report.document_size / 1024
        self.doc_info_label.setText(f"文档: {report.line_count} 行, {doc_size_kb:.1f} KB") 